package com.zcgk.core.domain;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zcgk.core.utils.PageUtils;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.util.Objects;

/****************************************************
 *
 * 封装返回值
 *
 *
 * @author Francis
 * @date 2020/2/4 13:28
 * @version 1.0
 **************************************************/
@Data
@ApiModel("返回值实体")
public class JsonResult<T> {

    @ApiModelProperty("自定义返回状态码")
    private Integer code;

    @ApiModelProperty("自定义返回信息")
    private String msg;

    @ApiModelProperty("自定义返回数据")
    private T data;

    @ApiModelProperty("分页信息")
    private DefaultPage<T> page;


    /**
     * 对外调用：成功的时候调用 (不带分页信息的，即：通常调用都调这个)。
     *      调用示例如下：
     *          无返回值，如，新增/删除成功后，无需返回值：  JsonResult.success(null);
     *          有返回值，如 编辑返显： JsonResult.success(data);
     *
     * @param data 返回的数据。无则填null。
     * @param <T> 泛型
     * @return json
     */
    public static<T> JsonResult<T> success(T data) {
        return new JsonResult<T>(data);
    }


    /**
     * 对外调用：成功的时候调用 (带分页信息的，即：分页查询都调这个)。
     *      调用示例如下：
     *
     * @param page Mybatis-plus 分页对象
     * @param <T> 泛型
     * @return json
     */
    public static<T> JsonResult<T> success4Page(Page<T> page) {
        return new JsonResult<>((T)page.getRecords()).setDefaultPage(PageUtils.trans2DefaultPage(page));
    }


    /**
     * 对外调用：失败的时候调用。
     *      调用示例如下：JsonResult.error(CodeMsg.ERROR_DEMO);
     *
     * @param codeMsg codeMsg
     * @param <T> 泛型
     * @return json
     */
    public static<T> JsonResult<T> error(CodeMsg codeMsg) {
        return new JsonResult<T>(codeMsg);
    }

    /**
     * 对外调用：失败的时候调用。(非特殊情况，禁止使用此方法)
     *      此方法当前用于封装参数校验的异常处理信息
     *
     * @param codeMsg codeMsg
     * @param <T> 泛型
     * @return json
     */
    public static<T> JsonResult<T> error(CodeMsg codeMsg, T data) {
        return new JsonResult<T>(codeMsg, data);
    }


    /**
     * 对外调用：通用返回。(非特殊情况，禁止使用此方法)
     *      此方法当前用于封装参数校验的异常处理信息
     *
     * @param code code
     * @param msg msg
     * @param data data
     * @param <T> 泛型
     * @return json
     */
    public static<T> JsonResult<T> common(Integer code, String msg, T data) {
        return new JsonResult<T>(code, msg, data);
    }


    /**
     * 成功 对应的 构造函数
     *
     * @param data data
     */
    private JsonResult(T data) {
        this.code = 200;
        this.msg = "SUCCESS";
        this.data = data;
    }


    /**
     * 失败 对应的 构造函数
     *
     * @param codeMsg codeMsg
     */
    private JsonResult(CodeMsg codeMsg) {
        if(!Objects.isNull(codeMsg)) {
            this.code = codeMsg.getCode();
            this.msg = codeMsg.getMsg();
        }
    }


    /**
     * 失败 对应的 构造函数 -- 特殊
     *
     * @param codeMsg codeMsg
     * @param data data
     */
    private JsonResult(CodeMsg codeMsg, T data) {
        if(!Objects.isNull(codeMsg)) {
            this.code = codeMsg.getCode();
            this.msg = codeMsg.getMsg();
        }

        if(!Objects.isNull(data)) {
            this.data = data;
        }
    }


    /**
     * 通用返回 对应的 构造函数
     *
     * @param code code
     * @param msg msg
     * @param data data
     */
    private JsonResult(Integer code, String msg, T data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }


    /**
     * 内部方法 -- 设置分页信息
     *
     * @param page 分页信息
     * @return
     */
    private JsonResult<T> setDefaultPage(DefaultPage<T> page) {
        this.page = page;

        return this;
    }

}
